package cc.rengu.igas.bomp.core.service.trans;

import cc.rengu.igas.bomp.common.constant.BompAppParamConstant;
import cc.rengu.igas.bomp.common.dao.*;
import cc.rengu.igas.bomp.common.dao.impl.*;
import cc.rengu.igas.bomp.common.entity.AuthUser;
import cc.rengu.igas.bomp.common.entity.ManagerInfo;
import cc.rengu.igas.bomp.common.entity.QrCodeInfo;
import cc.rengu.igas.bomp.common.entity.QrcodeBatchInfo;
import cc.rengu.igas.bomp.common.enums.QrBindStatusEnum;
import cc.rengu.igas.bomp.common.enums.QrCodeTypeEnum;
import cc.rengu.igas.bomp.common.enums.QrStatusEnum;
import cc.rengu.igas.bomp.common.enums.RespCodeEnum;
import cc.rengu.igas.bomp.core.service.base.ManageService;
import cc.rengu.igas.bomp.facade.request.MchntQrCodeBatchApplyRequest;
import cc.rengu.igas.bomp.facade.response.MchntQrCodeBatchApplyResponse;
import cc.rengu.igas.share.core.model.UserInfo;
import cc.rengu.igas.share.core.realize.UserService;
import cc.rengu.igas.share.core.realize.impl.UserServiceImpl;
import cc.rengu.oltp.service.common.constant.AppConfigConstant;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.dao.SysParamMapper;
import cc.rengu.oltp.service.common.dao.impl.SysParamMapperImpl;
import cc.rengu.oltp.service.common.entity.SysParam;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.utility.util.*;

import java.util.ArrayList;
import java.util.List;

/**
 * 商户收款聚合码批量申请服务
 * Created by 王成 on 2018/10/18.
 * <p>
 * 聚合码：  银行域名 +  /inf=S   +  国密加密的系统流水号sysSeqNum
 * 银联码：  银联域名 + /银联机构号 +  /inf=S  +国密加密的系统流水号sysSeqNum
 * <p>
 * 处理流程：
 * 1、根据法人行(inst_id)查询系统参数表，获取二维码类型；
 * 2、判断二维码类型
 * 2.1 聚合码：
 * （1）根据法人行(inst_id)查询系统参数表，获取法人行的二维码域名
 * （2）调用加密平台加密系统流水号（sysSeqNum）
 * （3）拼接聚合码  规则：银行域名 +  /inf=S   +  国密加密的系统流水号sysSeqNum
 * （4）新增数据到二维码信息表
 * 2.2 银联码：
 * （1）常量：银联码域名
 * （2）根据法人行(inst_id)查询系统参数表，获取法人行在银联的机构号
 * （2）调用加密平台加密系统流水号（sysSeqNum）
 * （3）拼接聚合码  规则：银联域名  https://qr.95516.com/ + 银联机构号 +  /inf=S  +国密加密的系统流水号sysSeqNum
 * （4）新增数据到二维码信息表
 */
public class MchntQrCodeBatchApplyService extends ManageService {

    /**
     * 调用加密平台，类型：0-加密 1-解密
     */
    private static final String ED_FUNC_FLAG = "0";

    /**
     * 交易金额来源 0-客户输入  1-固定金额
     */
    private static final String SRC_AMT_TYPE = "0";

    /**
     * 分隔符 /
     */
    private static final String NETWORK_SEPARATOR = "/";

    @Override
    protected Object bizBeforeCust() throws Exception {
        MchntQrCodeBatchApplyRequest mchntQrCodeBatchApplyRequest = new MchntQrCodeBatchApplyRequest();
        ConvertUtil.convertOutput(mchntQrCodeBatchApplyRequest);
        /* 参数合法性校验 */
        if (StringUtil.isEmptyOrNull(mchntQrCodeBatchApplyRequest.getApplyNum())
                || Integer.parseInt(mchntQrCodeBatchApplyRequest.getApplyNum()) < 1) {
            rglog.error("二维码申请数量:<{}>为空或 小于1!", mchntQrCodeBatchApplyRequest.getApplyNum());
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }

        return mchntQrCodeBatchApplyRequest;
    }

    @Override
    protected BizResponse bizProcessCust(Object request) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        MchntQrCodeBatchApplyRequest mchntQrCodeBatchApplyRequest = (MchntQrCodeBatchApplyRequest) request;
        BizResponse<MchntQrCodeBatchApplyResponse> bizResponse = new BizResponse<>();
        String instId = mchntQrCodeBatchApplyRequest.getHeader().getInstId();
        SysParamMapper sysParamMapper = new SysParamMapperImpl();

        /*根据instId查询二维码最大批量申请数目*/
        SysParam maxBatchApplyQrNumParam = sysParamMapper.selectSysParamByPrimaryKey(instId, BompAppParamConstant.MCHNT_PARAM_TYPE, BompAppParamConstant.MAX_BATCH_APPLY_QR_NUM);
        if (null == maxBatchApplyQrNumParam) {
            int maxBatchApplyQrNum = BompAppParamConstant.IGAS_MAX_BATCH_APPLY_QR_NUM;
            if (Integer.parseInt(mchntQrCodeBatchApplyRequest.getApplyNum()) > maxBatchApplyQrNum) {
                rglog.error("二维码申请数量:<{}>超过最大限制值<{}>!", mchntQrCodeBatchApplyRequest.getApplyNum(), maxBatchApplyQrNum);
                MchntQrCodeBatchApplyResponse mchntQrCodeBatchApplyResponse = new MchntQrCodeBatchApplyResponse();
                mchntQrCodeBatchApplyResponse.setRespCode(RespCodeEnum.MAX_BATCH_APPLY_QR_NUM.getRespCode());
                mchntQrCodeBatchApplyResponse.setRespDesc(RespCodeEnum.MAX_BATCH_APPLY_QR_NUM.getRespDesc() + maxBatchApplyQrNum);
                bizResponse.setRspSysId(AppParamConstant.SYS_ID);
                bizResponse.setRespCode(RespCodeEnum.GENERATE_MCHNT_QRCODE_ERROR.getRespCode());
                bizResponse.setRespDesc(RespCodeEnum.GENERATE_MCHNT_QRCODE_ERROR.getRespDesc());
                bizResponse.setResult(mchntQrCodeBatchApplyResponse);
                return bizResponse;
            }
        } else {
            String maxBatchApplyQrNum = maxBatchApplyQrNumParam.getParamValue();
            if (Integer.parseInt(mchntQrCodeBatchApplyRequest.getApplyNum()) > Integer.parseInt(maxBatchApplyQrNum)) {
                rglog.error("二维码申请数量:<{}>超过最大限制值<{}>!", mchntQrCodeBatchApplyRequest.getApplyNum(), maxBatchApplyQrNum);
                MchntQrCodeBatchApplyResponse mchntQrCodeBatchApplyResponse = new MchntQrCodeBatchApplyResponse();
                mchntQrCodeBatchApplyResponse.setRespCode(RespCodeEnum.MAX_BATCH_APPLY_QR_NUM.getRespCode());
                mchntQrCodeBatchApplyResponse.setRespDesc(RespCodeEnum.MAX_BATCH_APPLY_QR_NUM.getRespDesc() + maxBatchApplyQrNum);
                bizResponse.setRspSysId(AppParamConstant.SYS_ID);
                bizResponse.setRespCode(RespCodeEnum.GENERATE_MCHNT_QRCODE_ERROR.getRespCode());
                bizResponse.setRespDesc(RespCodeEnum.GENERATE_MCHNT_QRCODE_ERROR.getRespDesc());
                bizResponse.setResult(mchntQrCodeBatchApplyResponse);
                return bizResponse;
            }
        }

        /* 根据机构号获取二维码类型 */
        SysParam instQrCodeTypeSysParam = sysParamMapper.selectSysParamByPrimaryKey(instId, BompAppParamConstant.MCHNT_PARAM_TYPE, BompAppParamConstant.INST_QRCODE_TYPE);
        String qrCodeType = "";
        if (null == instQrCodeTypeSysParam) {
            /*数据库没配二维码类型，默认为收单聚合码*/
            qrCodeType = QrCodeTypeEnum.IGAS.getCodeType();
        } else {
            qrCodeType = instQrCodeTypeSysParam.getParamValue();
        }

        StringBuilder qrCode = new StringBuilder();
        if (QrCodeTypeEnum.CUPS.getCodeType().equals(qrCodeType)) {
            //银联二维码域名 https://qr.95516.com/
            qrCode.append(BompAppParamConstant.CUPS_QRCODE_DOMAIN_NAME);

            /* 银联码，获取法人行在银联的机构号 */
            SysParam unionPayCode = sysParamMapper.selectSysParamByPrimaryKey(instId, BompAppParamConstant.MCHNT_PARAM_TYPE, BompAppParamConstant.CUPS_INSR_ID);
            if (null == unionPayCode) {
                rglog.error("批量申请收款聚合码服务处理失败！机构二维码类型为银联二维码，获取法人行在银联的机构号失败！instId:{}", instId);
                throw new BizException(RespCodeEnum.GENERATE_MCHNT_QRCODE_ERROR.getRespCode(), RespCodeEnum.GENERATE_MCHNT_QRCODE_ERROR.getRespDesc());
            }

            qrCode.append(unionPayCode.getParamValue()).append(NETWORK_SEPARATOR);
        } else if (QrCodeTypeEnum.IGAS.getCodeType().equals(qrCodeType)) {
            //银行二维码域名
            SysParam bankDomainName = sysParamMapper.selectSysParamByPrimaryKey(instId, BompAppParamConstant.MCHNT_PARAM_TYPE, BompAppParamConstant.MCHNT_QRCODE_DOMAIN_NAME);
            if (null == bankDomainName) {
                rglog.error("批量申请收款聚合码服务处理失败！获取收款聚合码银行域名参数失败， instId:{}。", instId);
                throw new BizException(RespCodeEnum.GENERATE_MCHNT_QRCODE_ERROR.getRespCode(), RespCodeEnum.GENERATE_MCHNT_QRCODE_ERROR.getRespDesc());
            }

            qrCode.append(bankDomainName.getParamValue());
           /* if (!bankDomainName.getParamValue().endsWith(NETWORK_SEPARATOR)) {
                qrCode.append(NETWORK_SEPARATOR);
            }*/
        }

        qrCode.append("inf=S");

        BompSequenceMapper bompSequenceMapper = new BompSequenceMapperImpl();
        //生成批次号
        String applyBatchSeqNum = bompSequenceMapper.getNextApplyBatchNo();
        if (null == applyBatchSeqNum) {
            rglog.error("批量申请收款聚合码服务处理失败，生成申请批次序号失败!");
            throw new BizException(RespCodeEnum.GENERATE_SEQ_NO_ERROR.getRespCode(), RespCodeEnum.GENERATE_SEQ_NO_ERROR.getRespDesc());
        }
        //批次号生成规则：8位日期+6位时间+2位序列号
        applyBatchSeqNum = applyBatchSeqNum.substring(applyBatchSeqNum.length() - 2);
        String applyBatchNo = DateUtil.getCurrentDate() + DateUtil.getCurrentTime() + applyBatchSeqNum;

        //获取二维码列表信息
        List<QrCodeInfo> qrCodeInfoList = getQrCodeInfoList(mchntQrCodeBatchApplyRequest, instId, qrCode, bompSequenceMapper, applyBatchNo, qrCodeType);

        String orgCode = "";
        String oprId = "";
        if (!"MCMP".equals(mchntQrCodeBatchApplyRequest.getHeader().getChanlId())) {
            /*商户服务操作查询认证*/
            UserService userService = new UserServiceImpl();
            UserInfo userInfo = userService.getUserInfo(instId, mchntQrCodeBatchApplyRequest.getUserId(), mchntQrCodeBatchApplyRequest.getHeader().getSession());
            if (null == userInfo) {
                rglog.error("用户不存在");
                throw new BizException(RespCodeEnum.QUERY_AUTH_USER_IS_NULL.getRespCode(), RespCodeEnum.QUERY_AUTH_USER_IS_NULL.getRespDesc());
            }

            ManagerInfo managerInfo = null;
            ManagerInfoMapper managerInfoMapper = new ManagerInfoMapperImpl();
            if ("APP".equals(mchntQrCodeBatchApplyRequest.getHeader().getChanlId())) {
                managerInfo = managerInfoMapper.selectManagerInfoById(instId, mchntQrCodeBatchApplyRequest.getUserId());
            } else {
                managerInfo = managerInfoMapper.selectManagerInfoByOpenId(instId, userInfo.getUserApexMap().get("openId"));
            }
            if (null == managerInfo) {
                rglog.error("拓展经理信息不存在");
                throw new BizException(RespCodeEnum.QUERY_MANAGER_INFO_ERROR.getRespCode(), RespCodeEnum.QUERY_MANAGER_INFO_ERROR.getRespDesc());
            }
            orgCode = managerInfo.getSignInstId();
            oprId = managerInfo.getManagerId();
        } else {
            /*运营管理操作查询用户信息*/
            AuthUserMapper authUserMapper = new AuthUserMapperImpl();
            AuthUser authUser = authUserMapper.selectAuthUserById(mchntQrCodeBatchApplyRequest.getUserId());
            if (null == authUser) {
                rglog.error("用户不存在");
                throw new BizException(RespCodeEnum.QUERY_AUTH_USER_IS_NULL.getRespCode(), RespCodeEnum.QUERY_AUTH_USER_IS_NULL.getRespDesc());
            }

            orgCode = authUser.getOrgCode();
            oprId = authUser.getEmpNo();
            String userInstId = authUser.getInstId();
            /*判断是否是(admin)用户*/
            if (BompAppParamConstant.BASE_ISNT_ID.equals(userInstId) && !BompAppParamConstant.BASE_ISNT_ID.equals(instId)) {
                /*(admin)用户,机构号取法人行总行机构号*/
                orgCode = instId + BompAppParamConstant.INSTORGCODE;
            }
        }

        /* 开启数据库事务 */
        String dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(AppConfigConstant.DATABASE_CONF_NODE, AppConfigConstant.MCMP_POOL_NAME);
        String corporation = xmlTreeUtil.getXmlTreeStringValue(AppParamConstant.CORPORATION);
        if (null != corporation && !corporation.isEmpty()) {
            String dbPoolCashNode = corporation.trim() + AppParamConstant.DATABASE_CONF_NODE;
            dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(dbPoolCashNode, AppConfigConstant.MCMP_POOL_NAME);
        }
        DbsUtil dbsUtil = new DbsUtil(dbPoolName);
        dbsUtil.dbsBeginTransaction();
        QrCodeInfoMapper qrCodeInfoMapper = new QrCodeInfoMapperImpl();
        /* 批量生成并登记商户收款二维码 */
        for (QrCodeInfo qrCodeInfo : qrCodeInfoList) {
            insertQrCodeInfo(dbsUtil, qrCodeInfoMapper, qrCodeInfo);
        }

        /* 登记二维码批次信息表 */
        insertQrcodeBatchInfo(mchntQrCodeBatchApplyRequest, instId, applyBatchNo, dbsUtil, oprId, orgCode, qrCodeType);

        /* 结束数据库事务 */
        dbsUtil.dbsEndTransaction(true);

        /* 拼装应答报文 */
        MchntQrCodeBatchApplyResponse mchntQrCodeBatchApplyResponse = new MchntQrCodeBatchApplyResponse();
        mchntQrCodeBatchApplyResponse.setApplyBatchNo(applyBatchNo);
        bizResponse.setRspSysId(AppParamConstant.SYS_ID);
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        bizResponse.setResult(mchntQrCodeBatchApplyResponse);
        return bizResponse;
    }

    private void insertQrcodeBatchInfo(MchntQrCodeBatchApplyRequest mchntQrCodeBatchApplyRequest, String instId, String applyBatchNo, DbsUtil dbsUtil, String oprId, String orgCode, String qrCodeType) throws Exception {
        QrcodeBatchInfo qrcodeBatchInfo = new QrcodeBatchInfo();
        qrcodeBatchInfo.setId(RandomUtil.getUUID());
        qrcodeBatchInfo.setQrCodeBatchNo(applyBatchNo);
        qrcodeBatchInfo.setInstId(instId);
        qrcodeBatchInfo.setQrCodeType(qrCodeType);
        qrcodeBatchInfo.setQrCodeBatchStatus("01");
        int num = Integer.parseInt(mchntQrCodeBatchApplyRequest.getApplyNum());
        qrcodeBatchInfo.setQrCodeSum(num);
        qrcodeBatchInfo.setOprId(mchntQrCodeBatchApplyRequest.getUserId());
        qrcodeBatchInfo.setCrtOrgId(orgCode);
        String time = DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS");
        qrcodeBatchInfo.setCreateTime(time);

        QrcodeBatchInfoMapper qrcodeBatchInfoMapper = new QrcodeBatchInfoMapperImpl();
        int iReturnCode = qrcodeBatchInfoMapper.insertQrcodeBatchInfo(qrcodeBatchInfo);
        if (0 != iReturnCode) {
            rglog.error("登记二维码批次信息失败,iReturnCode:<{}>", qrcodeBatchInfo.getInstId(), iReturnCode);
            dbsUtil.dbsEndTransaction(false);
            throw new BizException(RespCodeEnum.REGISTER_QRCODE_INFO_ERROR.getRespCode(), RespCodeEnum.REGISTER_QRCODE_INFO_ERROR.getRespDesc());
        }
    }

    private List<QrCodeInfo> getQrCodeInfoList(MchntQrCodeBatchApplyRequest request,
                                               String instId,
                                               StringBuilder qrCode,
                                               BompSequenceMapper bompSequenceMapper,
                                               String applyBatchNo,
                                               String qrCodeType) throws Exception {
        int num = Integer.parseInt(request.getApplyNum());
        List<QrCodeInfo> qrCodeInfoList = new ArrayList<>();
        for (int i = 0; i < num; i++) {
            // qrCode生成规则：3位法人行+16位批次号+13位随机数
            String seq = instId + applyBatchNo + RandomUtil.randomNumStr(13);
//            ChannelCallCfg channelCallCfg = txnInfo.getChannelCallCfgList().get(0);

            //调用加密机平台进行 国密算法加密
//            EncyGenQrcodeDeRequest encyGenQrcodeDeRequest = new EncyGenQrcodeDeRequest();
//            //加密
//            encyGenQrcodeDeRequest.setEdFuncFlag(ED_FUNC_FLAG);
//            encyGenQrcodeDeRequest.setTxnNum(channelCallCfg.getCallChannelTxn());
//            encyGenQrcodeDeRequest.setMsgSrcId(ChannelEnum.BOMP.getChannelType());
//            encyGenQrcodeDeRequest.setInstId(instId);
//            //需要加密的数据信息 8位序列号
//            encyGenQrcodeDeRequest.setDataInfo(seq);
//            DubboService dubboService = new DubboServiceImpl();
//            Result<EncyGenQrcodeDeResponse> result = dubboService.callDubboService(DubboMethodConstant.DUBBO_ENCRYPT_PLAT_SUP_SERVICE,"encyGenQrcodeDe",encyGenQrcodeDeRequest);
//            EncyGenQrcodeDeResponse encyGenQrcodeDeResponse = result.getResult();
//            if (!result.isSuccess() || !DubboMethodConstant.DUBBO_SUCCESS.equals(encyGenQrcodeDeResponse.getRespCode())) {
//                rglog.error("批量申请收款聚合码服务处理失败！调用加密平台返回失败！errorCode:{},errorMsg:{}",
//                        encyGenQrcodeDeResponse.getRespCode(), encyGenQrcodeDeResponse.getRespDesc());
//                throw new BizException(RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespCode(), RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespDesc());
//            }
            String encyData = null;
            String itmeQrCode;

            itmeQrCode = qrCode + seq;
            rglog.debug("qrCode：{}", itmeQrCode);


            /* 登记商户收款聚合码信息 */
            QrCodeInfo qrCodeInfo = new QrCodeInfo();
            qrCodeInfo.setId(RandomUtil.getUUID());
            qrCodeInfo.setInstId(instId);
            //yyyyMMdd+8位
            qrCodeInfo.setApplyBatchNo(applyBatchNo);
            qrCodeInfo.setQrCodeType(qrCodeType);
            qrCodeInfo.setQrUrl(itmeQrCode);
            qrCodeInfo.setQrCode(seq);
            //0-客户输入  1-固定金额
            qrCodeInfo.setSrcAmtType(SRC_AMT_TYPE);
            qrCodeInfo.setQrStatus(QrStatusEnum.NORMAL.getStatus());
            //未绑定
            qrCodeInfo.setBindStatus(QrBindStatusEnum.UNBIND.getBindStatus());
            qrCodeInfo.setOprId(request.getUserId());
            String time = DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS");
            qrCodeInfo.setCreateTime(time);
            qrCodeInfo.setEffectiveTime(time);
            qrCodeInfo.setExpiryTime(BompAppParamConstant.DEFAULT_EXPIRY_DATE_QRCODE);
            qrCodeInfo.setQrNum(String.format("%06d", i));
            qrCodeInfoList.add(qrCodeInfo);
        }
        return qrCodeInfoList;
    }

    private void insertQrCodeInfo(DbsUtil dbsUtil, QrCodeInfoMapper qrCodeInfoMapper, QrCodeInfo qrCodeInfo) throws Exception {
        int iReturnCode = qrCodeInfoMapper.insertQrCodeInfoByTransaction(qrCodeInfo);
        if (0 != iReturnCode) {
            rglog.error("登记商户收款聚合码<{}>信息失败,iReturnCode:<{}>", qrCodeInfo.getQrCode(), iReturnCode);
            dbsUtil.dbsEndTransaction(false);
            throw new BizException(RespCodeEnum.REGISTER_QRCODE_INFO_ERROR.getRespCode(), RespCodeEnum.REGISTER_QRCODE_INFO_ERROR.getRespDesc());
        }
    }

    @Override
    protected void bizAfterCust(Object response) throws Exception {
        BizResponse bizResponse = (BizResponse) response;
        MchntQrCodeBatchApplyResponse mchntQrCodeBatchApplyResponse = (MchntQrCodeBatchApplyResponse) bizResponse.getResult();
        ConvertUtil.convertInput(mchntQrCodeBatchApplyResponse);
    }
}
